home *** CD-ROM | disk | FTP | other *** search
/ APDL Other Worlds / APDL Other Worlds Collection.iso / SF3000 / Extras / !SFskyedit / c / Preview < prev    next >
Encoding:
Text File  |  2003-10-16  |  13.0 KB  |  357 lines

  1. /*
  2.  *  SFskyedit - Star Fighter 3000 sky colours editor
  3.  *  Sky preview window
  4.  *  Copyright (C) 2001  Chris Bazley
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public Licence as published by
  8.  *  the Free Software Foundation; either version 2 of the Licence, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public Licence for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public Licence
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. #include "Preview.h"
  22.  
  23. /* ANSI library files */
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27.  
  28. /* RISC OS library files */
  29. #include "kernel.h"
  30. #include "swis.h"
  31. #include "wimp.h"
  32. #include "toolbox.h"
  33. #include "event.h"
  34. #include "wimplib.h"
  35. #include "window.h"
  36. #include "menu.h"
  37. #include "flex.h"
  38.  
  39. /* My library files */
  40. #include "err.h"
  41. #include "msgtrans.h"
  42. #include "Macros.h"
  43. #include "SFformats.h"
  44. #include "SprFormats.h"
  45. #include "NoBudge.h"
  46.  
  47. /* Local headers */
  48. #include "Utils.h"
  49. #include "EditSky.h"
  50. #include "Render.h"
  51. #include "Preview.h"
  52. #include "Main.h"
  53.  
  54. /* Gadgets */
  55. #define PREVIEW_SLIDER  0x00
  56. #define PREVIEW_NUMDISP 0x01
  57.  
  58. #define PREVIEW_MENU_MINSKY 0x00
  59. #define PREVIEW_MENU_STARS  0x01
  60.  
  61. /* Key shortcuts */
  62. #define KEY_SET_SKYHEIGHT  0x0a
  63. #define KEY_SET_STARHEIGHT 0x0b
  64. #define KEY_UP             0x0c
  65. #define KEY_DOWN           0x0d
  66. #define KEY_ESCAPE         0x0e
  67.  
  68. typedef struct _PreviewData
  69. {
  70.   ObjectId heightslider;
  71.   ObjectId prevmenu;
  72.   int render_height;
  73.   bool have_caret;
  74.   spriteareaheader *cached_image;
  75. } PreviewData;
  76.  
  77. /* ----------------------------------------------------------------------- */
  78. /*                       Function prototypes                               */
  79.  
  80. static ToolboxEventHandler _Preview_sliderhandler, _Preview_deletedhandler, _Preview_openhandler, _Preview_menuhandler, _Preview_keyhandler;
  81.  
  82. static WimpEventHandler _Preview_redrawhandler;
  83.  
  84. static void _Preview_setheight(PreviewData *preview_data, int height);
  85.  
  86. /* ----------------------------------------------------------------------- */
  87. /*                         Public functions                                */
  88.  
  89. ObjectId Preview_create(void)
  90. {
  91.   PreviewData *preview_data;
  92.   ObjectId window_id;
  93.   _kernel_swi_regs regs;
  94.   
  95.   /* Create data block for this window */
  96.   preview_data = malloc(sizeof(PreviewData));
  97.   if(preview_data == NULL)
  98.     MG_RETV("NoMem", NULL_ObjectId); /* failed */
  99.   preview_data->have_caret = false;
  100.  
  101.   /* Create sprite area to cache sky image */
  102.   if(!flex_alloc((flex_ptr)&preview_data->cached_image, sizeof(spriteareaheader) + sizeof(spriteheader) + (320*256))) {
  103.     MG("NoMem");
  104.     goto err_exit1; /* no room */
  105.   }
  106.  
  107.   preview_data->cached_image->size = sizeof(spriteareaheader) + sizeof(spriteheader) + (320*256);
  108.   preview_data->cached_image->first = sizeof(spriteareaheader);
  109.   regs.r[0] = SPRITEOP_INIT_AREA + SPRITEOP_USERAREA_SPRNAME;
  110.   regs.r[1] = (int)preview_data->cached_image;
  111.   if(E(_kernel_swi(OS_SpriteOp, ®s, ®s)))
  112.     goto err_exit2;
  113.  
  114.   regs.r[0] = SPRITEOP_CREATE + SPRITEOP_USERAREA_SPRNAME;
  115.   regs.r[1] = (int)preview_data->cached_image;
  116.   regs.r[2] = (int)"Cache";
  117.   regs.r[3] = 0; /* no palette */
  118.   regs.r[4] = 320;
  119.   regs.r[5] = 256;
  120.   regs.r[6] = 13; /* mode number */
  121.   if(E(_kernel_swi(OS_SpriteOp, ®s, ®s)))
  122.     goto err_exit2;
  123.  
  124.   /* Create Window object */
  125.   if(E(toolbox_create_object(0, "Preview", &window_id)))
  126.     goto err_exit2;
  127.   if(E(toolbox_set_client_handle(0, window_id, preview_data)))
  128.     goto err_exit3;
  129.   
  130.   /* Get IDs of attached objects */
  131.   if(E(window_get_tool_bars(Window_ExternalTopLeftToolbar, window_id, NULL, NULL, NULL, &preview_data->heightslider)))
  132.     goto err_exit3;
  133.   if(E(window_get_menu(0, window_id, &preview_data->prevmenu)))
  134.     goto err_exit3;
  135.   
  136.   /* Register event handlers
  137.      Note that ObjectDeleted handler is registered AFTER anything that could cause an error and therefore premature deletion!
  138. */
  139.   if(!E(event_register_wimp_handler(window_id, Wimp_ERedrawWindow, _Preview_redrawhandler, preview_data))
  140.   && !E(event_register_toolbox_handler(preview_data->prevmenu, Menu_Selection, _Preview_menuhandler, preview_data))
  141.   && !E(event_register_toolbox_handler(preview_data->heightslider, Slider_ValueChanged, _Preview_sliderhandler, preview_data))
  142.   && !E(event_register_toolbox_handler(window_id, Window_AboutToBeShown, _Preview_openhandler, preview_data))
  143.   && !E(event_register_toolbox_handler(window_id, Window_HasBeenHidden, hand_back_caret, &preview_data->have_caret))
  144.   && !E(event_register_wimp_handler(window_id, -1, watch_caret, &preview_data->have_caret))
  145.   && !E(event_register_toolbox_handler(window_id, -1, _Preview_keyhandler, preview_data))
  146.   && !E(event_register_toolbox_handler(window_id, Toolbox_ObjectDeleted, _Preview_deletedhandler, preview_data)))
  147.     return window_id; /* success */
  148.   
  149.   err_exit3:
  150.     toolbox_delete_object(0, window_id);
  151.   err_exit2:
  152.     flex_free((flex_ptr)&preview_data->cached_image);
  153.   err_exit1:
  154.     free(preview_data);
  155.     return NULL_ObjectId; /* failed */
  156. }
  157.  
  158. /* -------------------------------------------------------------------------- */
  159.  
  160. void Preview_rendersky(ObjectId objectref)
  161. {
  162.   BBox redraw_box;
  163.   spriteheader *first_spr;
  164.   ObjectId editwin;
  165.   PreviewData *preview_data;
  166.   ViewData *view_data;
  167.  
  168.   /* Get data associated with preview and editing windows */ 
  169.   E_RET(toolbox_get_client_handle(0, objectref, (void **)&preview_data));
  170.   
  171.   E_RET(toolbox_get_ancestor(0, objectref, &editwin, NULL));
  172.   E_RET(toolbox_get_client_handle(0, editwin, (void **)&view_data));
  173.   
  174.   /* Render sky to image cache at current height */
  175.   nobudge_register(32);
  176.   first_spr = (spriteheader *)((int)preview_data->cached_image + preview_data->cached_image->first);
  177.   sky_drawsky(preview_data->render_height, &view_data->sky, (void *)((int)first_spr + first_spr->image), (256*320)-4);
  178.   nobudge_deregister();
  179.  
  180.   /* Force redraw of window */
  181.   if(!E(window_get_extent(0, objectref, &redraw_box))) {
  182.     RE(window_force_redraw(0, objectref, &redraw_box));
  183.   }
  184. }
  185.  
  186. /* ----------------------------------------------------------------------- */
  187. /*                          Private handlers                               */
  188.  
  189. static int _Preview_openhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  190. {
  191.   /* Start at ground level */
  192.   _Preview_setheight((PreviewData *)handle, 0);
  193.  
  194.   /* Render sky preview */
  195.   Preview_rendersky(id_block->self_id);
  196.   return 1; /* claim event */
  197. }
  198.  
  199. /* ----------------------------------------------------------------------- */
  200.  
  201. static int _Preview_deletedhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  202. {
  203.   PreviewData *preview_data = (PreviewData *)handle;
  204.   
  205.   /* Remove handlers */
  206.   RE(event_deregister_toolbox_handler(preview_data->heightslider, Slider_ValueChanged, _Preview_sliderhandler, handle));
  207.   RE(event_deregister_toolbox_handler(id_block->self_id, Toolbox_ObjectDeleted, _Preview_deletedhandler, handle));
  208.   RE(event_deregister_toolbox_handler(id_block->self_id, Window_AboutToBeShown, _Preview_openhandler, handle));
  209.   RE(event_deregister_wimp_handler(id_block->self_id, Wimp_ERedrawWindow, _Preview_redrawhandler, handle));
  210.   RE(event_deregister_toolbox_handler(id_block->self_id, -1, _Preview_keyhandler, handle));
  211.   RE(event_deregister_toolbox_handler(preview_data->prevmenu, Menu_Selection, _Preview_menuhandler, handle));
  212.   RE(event_deregister_toolbox_handler(id_block->self_id, Window_HasBeenHidden, hand_back_caret, NULL));
  213.  
  214.   /* Free image cache */
  215.   flex_free((flex_ptr)&preview_data->cached_image);
  216.   /* Free preview data block */
  217.   free(preview_data);
  218.   return 1; /* claim event */
  219. }
  220.  
  221. /* -------------------------------------------------------------------------- */
  222.  
  223. static int _Preview_keyhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  224. {
  225.   PreviewData *preview_data = (PreviewData *)handle;
  226.   int temp_renderheight;
  227.   
  228.   /* Handle hotkey events */
  229.   switch(event_code) {
  230.   
  231.     case KEY_SET_SKYHEIGHT: /* Ctrl-M Set minimum sky rendering height */
  232.       /* Shift viewing height to new ground 0 (so it looks the same) */
  233.       temp_renderheight = preview_data->render_height;
  234.       _Preview_setheight(preview_data, 0);
  235.       
  236.       /* Tell edit window to set minimum sky height and redraw */
  237.       EditSky_set_minheight(id_block->ancestor_id, temp_renderheight);
  238.       return 1; /* claim event */
  239.       
  240.     case KEY_SET_STARHEIGHT:
  241.       /* Ctrl-S Set height to start plotting stars */
  242.       EditSky_set_starheight(id_block->ancestor_id, preview_data->render_height);
  243.       return 1; /* claim event */
  244.        
  245.     case KEY_UP:        
  246.       /* Up - increase viewing height */
  247.       if(preview_data->render_height >= 2250)
  248.         return 1; /* claim event */
  249.       _Preview_setheight(preview_data, preview_data->render_height+10);
  250.       Preview_rendersky(id_block->self_id);
  251.       return 1; /* claim event */
  252.       
  253.     case KEY_DOWN:      
  254.       /* Down - decrease viewing height */
  255.       if(preview_data->render_height <= 0)
  256.         return 1; /* claim event */
  257.       _Preview_setheight(preview_data, preview_data->render_height-10);
  258.       Preview_rendersky(id_block->self_id);
  259.       return 1; /* claim event */
  260.  
  261.     case KEY_ESCAPE:
  262.       /* ESC - Close preview */
  263.       RE(toolbox_hide_object(0, id_block->self_id));
  264.       /* N.B. Don't need to worry about the window being iconised
  265.       since iconised windows get no keypresses */
  266.       return 1; /* claim event */
  267.   }
  268.   return 0; /* Not an event that we handle */
  269. }
  270.  
  271. /* -------------------------------------------------------------------------- */
  272.  
  273. static int _Preview_menuhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  274. {
  275.   PreviewData *preview_data = (PreviewData *)handle;
  276.   int temp_renderheight;
  277.   
  278.   /* Handle menu selections */
  279.   switch(id_block->self_component) {
  280.     case PREVIEW_MENU_MINSKY:
  281.       /* Shift viewing height to new ground 0 (i.e. same!) */
  282.       temp_renderheight = preview_data->render_height;
  283.       _Preview_setheight(preview_data, 0);
  284.       /* Tell edit window to set minimum sky height and redraw */
  285.       EditSky_set_minheight(id_block->ancestor_id, temp_renderheight);
  286.       return 1; /* claim event */
  287.          
  288.     case PREVIEW_MENU_STARS:
  289.       /* Set height to start plotting stars */
  290.       EditSky_set_starheight(id_block->ancestor_id, preview_data->render_height);
  291.       return 1; /* claim event */
  292.   }
  293.   return 0; /* event not handled */
  294. }
  295.  
  296. /* -------------------------------------------------------------------------- */
  297.  
  298. static int _Preview_sliderhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  299. {
  300.   PreviewData *preview_data = (PreviewData *)handle;
  301.   
  302.   if(id_block->self_component != PREVIEW_SLIDER
  303.   || ((SliderValueChangedEvent *)event)->new_value == preview_data->render_height)
  304.     return 0; /* Wrong component or no change in value */
  305.  
  306.   /* Set viewing height for sky render */
  307.   preview_data->render_height = ((SliderValueChangedEvent *)event)->new_value;
  308.   RE(numberrange_set_value(0, id_block->self_id, PREVIEW_NUMDISP, preview_data->render_height));
  309.   Preview_rendersky(id_block->parent_id);
  310.   return 1; /* claim event */
  311. }
  312.  
  313. /* ----------------------------------------------------------------------- */
  314.  
  315. static int _Preview_redrawhandler(int event_code, WimpPollBlock *event, IdBlock *id_block, void *handle)
  316. {
  317.   /* Custom redraw from cached sky image */
  318.   PreviewData *preview_data = (PreviewData *)handle;
  319.   WimpRedrawWindowBlock block;
  320.   int more, botleft_x, botleft_y;
  321.   _kernel_swi_regs regs;
  322.  
  323.   nobudge_register(1024);
  324.   block.window_handle = ((WimpRedrawWindowRequestEvent)event->redraw_window_request).window_handle;
  325.   E_RETV(wimp_redraw_window(&block, &more), 1);
  326.   botleft_x = block.visible_area.xmin - block.xscroll;
  327.   botleft_y = block.visible_area.ymax - block.yscroll - 512; /* get origin */
  328.   
  329.   while (more) {
  330.     regs.r[0] = SPRITEOP_PLOTSCALED + SPRITEOP_USERAREA_SPRPTR;
  331.     regs.r[1] = (int)preview_data->cached_image; /* sprite area */
  332.     regs.r[2] = (int)preview_data->cached_image + preview_data->cached_image->first; /* sprite pointer */
  333.     regs.r[3] = botleft_x; /* X coordinate */
  334.     regs.r[4] = botleft_y; /* Y coordinate */
  335.     regs.r[5] = 0; /* plot action */
  336.     regs.r[6] = (int)scale_factors; /* scale factors */
  337.     regs.r[7] = (int)transtable;
  338.     RE(_kernel_swi(OS_SpriteOp, ®s, ®s));
  339.     E_RETV(wimp_get_rectangle(&block, &more), 1);
  340.   }
  341.   nobudge_deregister();
  342.  
  343.   return 1; /* claim event */
  344. }
  345.  
  346. /* ----------------------------------------------------------------------- */
  347. /*                         Private functions                               */
  348.  
  349. static void _Preview_setheight(PreviewData *preview_data, int height)
  350. {
  351.   /* Set viewing height and attached slider/numeric display */
  352.  
  353.   RE(slider_set_value(0, preview_data->heightslider, PREVIEW_SLIDER, height));
  354.   RE(numberrange_set_value(0, preview_data->heightslider, PREVIEW_NUMDISP, height));
  355.   preview_data->render_height = height;
  356. }
  357.